package org.foreningsgatan.genetics.racers.manual;

import static org.foreningsgatan.genetics.racers.Configuration.sTargetFPS;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.swing.JFrame;

import org.foreningsgatan.genetics.SimulationObserver;
import org.foreningsgatan.genetics.racers.Actions;
import org.foreningsgatan.genetics.racers.RacingSimulation;
import org.foreningsgatan.genetics.racers.visual.RacerComponent;

public class ManualCarTest {
	private RacingSimulation simulation;
	private RacerComponent component;
	private JFrame frame;
	
	private void initSimulation() {
		simulation = new RacingSimulation();
		simulation.resetAll();
	}
	
	private void initUserInterface() {
		component = new RacerComponent(simulation);
		
		frame = new JFrame();
		frame.getContentPane().add(component);
		frame.pack();
		frame.setVisible(true);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}
	
	private void run() {
		KeyboardRunnable runnable = new KeyboardRunnable();
		runnable.addObserver(component);
		
		frame.addKeyListener(runnable);
		
		new Thread(runnable).start();
	}
	
	public ManualCarTest() throws Exception {
		initSimulation();
		initUserInterface();
	}
	
	public static void main(String[] args) throws Exception {
		ManualCarTest test = new ManualCarTest();
		test.run();
	}
	
	class KeyboardRunnable implements Runnable, KeyListener {
		private List<SimulationObserver> observers;
		private Map<Integer, Boolean> isPressed;
		
		public void addObserver(SimulationObserver o) {
			observers.add(o);
		}

		public KeyboardRunnable() {
			observers = new LinkedList<SimulationObserver>();
			isPressed = new HashMap<Integer, Boolean>();
		}
		
		private boolean isPressed(int keyCode) {
			return (isPressed.get(keyCode) != null) && isPressed.get(keyCode);
		}
		
		@Override
		public void run() {
			while (simulation.simulationActive()) {
				if (isPressed(KeyEvent.VK_UP)) {
					simulation.perform(Actions.RaiseSpeed);
				}
				
				if (isPressed(KeyEvent.VK_DOWN)) {
					simulation.perform(Actions.Break);
				}
				
				if (isPressed(KeyEvent.VK_RIGHT)) {
					simulation.perform(Actions.SoftTurnLeft);
				}
				
				if (isPressed(KeyEvent.VK_LEFT)) {
					simulation.perform(Actions.SoftTurnRight);
				}
				
				simulation.act();
				
				for (SimulationObserver o: observers) {
					o.update();
				}
				
				try {
					Thread.sleep(1000 / sTargetFPS);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}

		@Override
		public void keyPressed(KeyEvent e) {
			isPressed.put(e.getKeyCode(), true);
		}

		@Override
		public void keyReleased(KeyEvent e) {
			isPressed.put(e.getKeyCode(), false);
		}

		@Override
		public void keyTyped(KeyEvent e) {}
	}
}
